import os
import re
import tkinter as tk
from tkinter import filedialog, messagebox
from pathlib import Path

class ActorLibraryProcessor:
    def __init__(self):
        self.root_dir = None
        self.output_dir = None
        self.base_dir = Path("G:/emby")  # 固定的相对路径根目录
        
    def select_directories(self):
        """弹窗选择目录"""
        root = tk.Tk()
        root.withdraw()  # 隐藏主窗口
        
        # 选择包含演员子文件夹的根目录
        self.root_dir = filedialog.askdirectory(
            title="选择包含演员子文件夹的根目录"
        )
        if not self.root_dir:
            return False
        
        # 验证根目录是否是base_dir的子目录
        try:
            if not Path(self.root_dir).is_relative_to(self.base_dir):
                messagebox.showerror("错误", f"选择的目录必须是 {self.base_dir} 的子目录！")
                return False
        except AttributeError:
            if not self.root_dir.startswith(str(self.base_dir)):
                messagebox.showerror("错误", f"选择的目录必须是 {self.base_dir} 的子目录！")
                return False
        
        # 选择md文件输出目录
        self.output_dir = filedialog.askdirectory(
            title="选择md文件输出目录",
            initialdir=self.root_dir
        )
        if not self.output_dir:
            return False
        
        # 验证输出目录是否是base_dir的子目录
        try:
            if not Path(self.output_dir).is_relative_to(self.base_dir):
                messagebox.showerror("错误", f"输出目录必须是 {self.base_dir} 的子目录！")
                return False
        except AttributeError:
            if not self.output_dir.startswith(str(self.base_dir)):
                messagebox.showerror("错误", f"输出目录必须是 {self.base_dir} 的子目录！")
                return False
        
        return True
    
    def scan_actor_folders(self):
        """扫描根目录下的所有子文件夹（演员文件夹）"""
        if not self.root_dir:
            return []
        
        actor_folders = []
        for item in Path(self.root_dir).iterdir():
            if item.is_dir():
                actor_folders.append(item)
        
        return actor_folders
    
    def parse_folder_name(self, folder_path):
        """
        解析文件夹名称，提取罩杯和名字
        格式：罩杯+空格+名字，例如："C 小野六花"
        """
        folder_name = folder_path.name
        
        # 匹配格式：一个字母（罩杯）+ 空格 + 中文/日文名字
        match = re.match(r'^([A-Z])\s+([\u4e00-\u9fff\u3040-\u309f\u30a0-\u30ff\s]+)$', folder_name)
        
        if match:
            cup = match.group(1)  # 罩杯
            name = match.group(2).strip()  # 名字，去除前后空格
            return {
                'cup': cup,
                'name': name,
                'folder_name': folder_name,
                'parsed_successfully': True
            }
        else:
            # 尝试其他可能的格式
            # 格式：罩杯字母 + 名字（无空格）
            match_no_space = re.match(r'^([A-Z])([\u4e00-\u9fff\u3040-\u309f\u30a0-\u30ff\s]+)$', folder_name)
            if match_no_space:
                cup = match_no_space.group(1)
                name = match_no_space.group(2).strip()
                return {
                    'cup': cup,
                    'name': name,
                    'folder_name': folder_name,
                    'parsed_successfully': True
                }
            
            # 如果无法解析，使用整个文件夹名作为名字，罩杯设为未知
            return {
                'cup': '未知',
                'name': folder_name,
                'folder_name': folder_name,
                'parsed_successfully': False
            }
    
    def scan_media_files(self, folder_path):
        """扫描演员文件夹内的媒体文件"""
        image_extensions = {'.jpg', '.jpeg', '.png', '.gif', '.bmp'}
        video_extensions = {'.mp4', '.avi', '.mov', '.wmv', '.flv', '.mkv', '.webm'}
        
        image_files = []
        video_files = []
        
        for file_path in folder_path.rglob('*'):
            if file_path.is_file():
                ext = file_path.suffix.lower()
                if ext in image_extensions:
                    image_files.append(file_path)
                elif ext in video_extensions:
                    video_files.append(file_path)
        
        return image_files, video_files
    
    def get_relative_path(self, file_path):
        """获取相对于base_dir的路径（Obsidian格式）"""
        try:
            relative_path = Path(file_path).relative_to(self.base_dir)
            # 将Windows路径分隔符转换为Obsidian使用的正斜杠
            obsidian_path = str(relative_path).replace('\\', '/')
            return obsidian_path
        except ValueError as e:
            print(f"路径计算错误: {file_path} -> {e}")
            # 如果路径不在base_dir下，返回相对于演员文件夹的路径
            try:
                relative_path = Path(file_path).relative_to(Path(self.root_dir))
                obsidian_path = str(relative_path).replace('\\', '/')
                return obsidian_path
            except ValueError:
                return str(file_path.name)
    
    def create_actor_md_content(self, actor_info, image_files, video_files):
        """创建演员md文件内容"""
        # Front matter部分
        front_matter = f"""---
tags:
  - #{actor_info['name']}
type: actor
actor_id: 
name:
  - {actor_info['name']}
aliases:
link:  
罩杯: {actor_info['cup']}
风格:
  - 纯
  - 骚
气质:
  - 少女
  - 少妇
  - 熟女
体型:
  - 大只马
  - 中等马
  - 小只马
演技:
  - 三星（不错）
  - 四星（甚好）
  - 五星（极好）
  - 二星（欠佳）
---
"""
        
        # 图片部分
        content = "# 图片\n"
        if image_files:
            for img_file in sorted(image_files):
                rel_path = self.get_relative_path(img_file)
                content += f"![[{rel_path}]]\n"
        else:
            content += "（暂无图片）\n"
        content += "\n"
        
        # 视频部分
        content += "# 视频\n"
        if video_files:
            for vid_file in sorted(video_files):
                rel_path = self.get_relative_path(vid_file)
                content += f"![[{rel_path}]]\n"
        else:
            content += "（暂无视频）\n"
        content += "\n"
        
        # 作品部分
        content += "# 作品\n"
        content += "（待添加作品列表）\n"
        
        return front_matter + content
    
    def process_actor_folders(self):
        """主处理函数"""
        print(f"相对路径基准目录: {self.base_dir}")
        
        if not self.select_directories():
            print("目录选择取消，程序退出")
            return
        
        print(f"演员文件夹根目录: {self.root_dir}")
        print(f"输出目录: {self.output_dir}")
        
        # 显示相对路径示例
        try:
            relative_example = Path(self.root_dir).relative_to(self.base_dir)
            print(f"相对路径示例: {relative_example}")
        except ValueError:
            print("警告：根目录不在基准目录下")
        
        print("开始扫描演员文件夹...")
        actor_folders = self.scan_actor_folders()
        print(f"找到 {len(actor_folders)} 个演员文件夹")
        
        if not actor_folders:
            messagebox.showinfo("提示", "未找到任何演员文件夹！")
            return
        
        # 创建输出目录
        Path(self.output_dir).mkdir(exist_ok=True)
        
        created_count = 0
        updated_count = 0
        parse_failed_folders = []
        
        for folder_path in actor_folders:
            # 解析文件夹名称
            actor_info = self.parse_folder_name(folder_path)
            
            if not actor_info['parsed_successfully']:
                parse_failed_folders.append(actor_info['folder_name'])
                print(f"解析失败: {actor_info['folder_name']}")
                continue
            
            print(f"解析成功: {actor_info['folder_name']} -> 罩杯:{actor_info['cup']}, 名字:{actor_info['name']}")
            
            # 扫描媒体文件
            image_files, video_files = self.scan_media_files(folder_path)
            print(f"  找到 {len(image_files)} 张图片, {len(video_files)} 个视频")
            
            # 显示路径示例
            if image_files:
                sample_path = self.get_relative_path(image_files[0])
                print(f"  路径示例: ![[{sample_path}]]")
            
            # 创建md文件
            md_filename = f"{actor_info['name']}.md"
            md_file_path = Path(self.output_dir) / md_filename
            
            # 检查文件是否已存在
            if md_file_path.exists():
                updated_count += 1
                action = "更新"
            else:
                created_count += 1
                action = "创建"
            
            # 创建文件内容
            content = self.create_actor_md_content(actor_info, image_files, video_files)
            
            try:
                with open(md_file_path, 'w', encoding='utf-8') as f:
                    f.write(content)
                print(f"{action}文件: {md_filename}")
            except Exception as e:
                print(f"写入文件失败 {md_filename}: {e}")
        
        # 显示结果摘要
        summary = (f"处理完成！\n"
                  f"相对路径基准: {self.base_dir}\n"
                  f"扫描文件夹总数: {len(actor_folders)}\n"
                  f"创建: {created_count} 个演员文件\n"
                  f"更新: {updated_count} 个演员文件\n"
                  f"解析失败: {len(parse_failed_folders)} 个文件夹")
        
        if parse_failed_folders:
            summary += f"\n\n解析失败的文件夹:\n" + "\n".join(parse_failed_folders)
        
        print(f"\n{summary}")
        messagebox.showinfo("处理完成", summary.split('\n\n')[0])  # 只显示摘要部分

def main():
    processor = ActorLibraryProcessor()
    processor.process_actor_folders()

if __name__ == "__main__":
    main()